package com.gome.boot.common.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import java.io.IOException;

/**
 * JSON/XML工具类.
 * <br/>基于Jackson实现.
 *
 * @author baoxiufeng
 */
public final class JacksonUtils {

    /**
     * XML与Object互转对象
     */
    private volatile static XmlMapper xmlMapper;

    /**
     * JSON与Object互转对象
     */
    private volatile static ObjectMapper mapper;

    /**
     * 获取XML与Object互转对象.
     *
     * @return XML与Object互转对象
     */
    private static XmlMapper getXmlMapper() {
        if (xmlMapper == null) {
            synchronized (XmlMapper.class) {
                if (xmlMapper == null) {
                    xmlMapper = new XmlMapper();
                    xmlMapper.setSerializationInclusion(JsonInclude.Include.USE_DEFAULTS);
                    xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
                    xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                }
            }
        }
        return xmlMapper;
    }

    /**
     * 获取JSON与Object互转对象.
     *
     * @return JSON与Object互转对象
     */
    private static ObjectMapper getMapper() {
        if (mapper == null) {
            synchronized (ObjectMapper.class) {
                if (mapper == null) {
                    mapper = new ObjectMapper();
                    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
                    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                }
            }
        }
        return mapper;
    }

    /**
     * 转换XML内容到指定类型的对象.
     *
     * @param xml   XML内容
     * @param clazz 待转换的对象类型
     * @param <T>   转换后对象类型泛型
     * @return 转换后的对象
     */
    public static <T> T convertXmlToObject(String xml, Class<T> clazz) {
        if (xml != null) {
            try {
                return getXmlMapper().readValue(xml, clazz);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

    /**
     * 转换JSON内容到指定类型的对象.
     *
     * @param json  JSON内容
     * @param clazz 待转换的对象类型
     * @param <T>   转换后对象类型泛型
     * @return 转换后的对象
     */
    public static <T> T convertJsonToObject(String json, Class<T> clazz) {
        if (json != null) {
            try {
                return getMapper().readValue(json, clazz);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换对象到XML串.
     *
     * @param obj 待转换的对象
     * @return 转换后的XML串
     */
    public static String convertObjectToXml(Object obj) {
        if (obj != null) {
            try {
                return getXmlMapper().writeValueAsString(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换对象到JSON串.
     *
     * @param obj 待转换的对象
     * @return 转换后的JSON串
     */
    public static String convertObjectToJson(Object obj) {
        if (obj != null) {
            try {
                return getMapper().writeValueAsString(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换XML内容到指定类型的对象.
     *
     * @param mapper 自定义的映射对象
     * @param xml    XML内容
     * @param clazz  待转换的对象类型
     * @param <T>    转换后对象类型泛型
     * @return 转换后的对象
     */
    public static <T> T convertXmlToObject(XmlMapper mapper, String xml, Class<T> clazz) {
        if (xml != null) {
            try {
                return mapper.readValue(xml, clazz);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换JSON内容到指定类型的对象.
     *
     * @param mapper 自定义的映射对象
     * @param json   JSON内容
     * @param clazz  待转换的对象类型
     * @param <T>    转换后对象类型泛型
     * @return 转换后的对象
     */
    public static <T> T convertJsonToObject(ObjectMapper mapper, String json, Class<T> clazz) {
        if (json != null) {
            try {
                return mapper.readValue(json, clazz);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换对象到XML串.
     *
     * @param mapper 自定义的映射对象
     * @param obj    待转换的对象
     * @return 转换后的XML串
     */
    public static String convertObjectToXml(XmlMapper mapper, Object obj) {
        if (obj != null) {
            try {
                return mapper.writeValueAsString(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 转换对象到JSON串.
     *
     * @param mapper 自定义的映射对象
     * @param obj    待转换的对象
     * @return 转换后的JSON串
     */
    public static String convertObjectToJson(ObjectMapper mapper, Object obj) {
        if (obj != null) {
            try {
                return mapper.writeValueAsString(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
